// Unity C# reference source
// Copyright (c) Unity Technologies. For terms of use, see
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License

using System;
using UnityEngine;
using UnityEngine.Bindings;
using Object = UnityEngine.Object;

namespace UnityEditor.Build.Reporting
{
    ///<summary>An extension to the <see cref="BuildReport" /> class that tracks how Assets contribute to the size of the build.</summary>
    ///<remarks>The build process generates a PackedAssets object for each Serialized File, resS and resource file generated by a build.  Serialized Files contain serialized Unity Objects from scenes and assets.
    ///
    ///The PackedAsset information can be used to analyze how specific assets or types contribute to the size of the build, for example to calculate the total size of all textures.
    ///
    ///Example file names for Serialized Files in the output of a Player build are <c>resources.assets</c>, <c>sharedassets0.assets</c> and <c>globalgamemanagers.assets</c>.
    ///Note: The content of scenes in the output of a Player build are written to Serialized Files with the names level0, level1, level2 etc.
    ///However there are no PackedAsset objects generated for level files, nor for the <c>globalgamemanager</c> file.
    ///
    ///AssetBundles containing assets will have a single Serialized File, with a name like "CAB-b8befc517982290c55526f35cbb7f03d".  AssetBundles containing scenes will contain multiple Serialized Files.
    ///
    ///The PackedAssets for a Serialized File records the size of the header in the <c>overhead</c> property, and then information about each object in the <c>contents</c> property.
    ///
    ///Files with the <c>.resource</c> contain audio or video data which is referenced by an <see cref="AudioClip" /> or <see cref="VideoClip" /> object inside the associated Serialized File.
    ///For example <c>level1.resource</c> contains audio and video data from objects inside the Serialized File <c>level1</c>.
    ///The PackedAsset for a .resource file records information about the originating asset for each blob of audio or video data in the .resource file.
    ///
    ///Similarly, the PackedAsset object for a .resS file records information about the size and origin of <see cref="Texture" /> and <see cref="Mesh" /> data inside the file.
    ///
    ///Note: For large builds the PackedAsset objects can grow very large, and consume a significant amount of memory.  When using this data it is recommended to do a single pass through the data to populate smaller data structures or to export it to another format, as required by external tools.</remarks>
    ///<example>
    ///  <code><![CDATA[
    ///using UnityEngine;
    ///using UnityEditor;
    ///using UnityEditor.Build.Reporting;
    ///using System.Text;
    ///
    ///public class BuildReportPackedAssetsExample
    ///{
    ///    [MenuItem("Example/Show PackedAssets from Latest Build")]
    ///    static void ShowPackedAssets()
    ///    {
    ///        var buildReport = BuildReport.GetLatestReport();
    ///
    ///        if (buildReport == null)
    ///        {
    ///            Debug.Log("Please run a Player or AssetBundle build, then try again");
    ///            return;
    ///        }
    ///
    ///        var sb = new StringBuilder();
    ///        var packedAssets = buildReport.packedAssets;
    ///
    ///        sb.AppendLine("Packed Assets:");
    ///        foreach (var packedAsset in buildReport.packedAssets)
    ///        {
    ///            var packedAssetInfoArray = packedAsset.contents;
    ///            sb.AppendLine($"  {packedAsset.shortPath} Item count: {packedAssetInfoArray.Length}");
    ///        }
    ///
    ///        //Example output:
    ///
    ///        //Packed Assets:
    ///        //  globalgamemanagers.assets Item count: 11
    ///        //  resources.assets Item count: 2
    ///        // etc.
    ///        Debug.Log(sb.ToString());
    ///    }
    ///}
    ///]]></code>
    ///</example>
    ///<seealso cref="Build.Reporting.PackedAssetInfo" />
    [NativeType(Header = "Modules/BuildReportingEditor/Public/PackedAssets.h")]
    [NativeClass("BuildReporting::PackedAssets")]
    public sealed class PackedAssets : Object
    {
        private const string fileObsoleteMessage = "Report file index is no longer available. To find the matching report file for a particular asset the recommended way is to do a filename lookup in the report.";
        [Obsolete(fileObsoleteMessage, true)]
        public uint file => throw new NotSupportedException(fileObsoleteMessage);

        ///<summary>The file name</summary>
        ///<remarks>For player builds this the filename relative to the Data folder of the build, for example "globalgamemanagers.assets.resS".
        ///
        ///For an AssetBundle this is the filename inside the Unity Archive file, for example "CAB-cc6c60ef8808e0fc6663136604321554" and "CAB-cc6c60ef8808e0fc6663136604321554.resS".</remarks>
        ///<seealso cref="Build.Reporting.BuildFile" />
        public string shortPath
        {
            get { return GetShortPath(); }
        }

        ///<summary>The size of the header section of the referenced file.</summary>
        ///<remarks>Some file formats have no header, in which case this returns zero.</remarks>
        public ulong overhead
        {
            get { return GetOverhead(); }
        }

        ///<summary>An array of <see cref="PackedAssetInfo" /> objects that holds information about the content portion of the referenced file.</summary>
        ///<remarks>A Serialized File is made up of a header section, and then a flat list of the objects, in their binary serialized form.
        ///Each entry in the PackedAssetInfo array corresponds to one of these serialized objects, in the order they are saved in the file.
        ///
        ///Similarly a .resS or .resource file is made of a sequence of binary blobs of audio, video, texture, mesh or other large data types. The PackedAssetInfo array has an entry for each of these blobs.</remarks>
        public PackedAssetInfo[] contents
        {
            get { return GetContents(); }
        }

        internal extern string GetShortPath();

        internal extern ulong GetOverhead();

        internal extern PackedAssetInfo[] GetContents();
    }
}
